
#pragma once
#include <memory>
#include <functional>
#include <vector>
#include <deque>

class Instance
{
public:
	Instance();
	virtual ~Instance();
};

typedef std::shared_ptr<Instance> InstancePtr;

class InstanceManager
{
public:
	~InstanceManager();

protected:
	InstanceManager() = default;
	InstanceManager(const InstanceManager&) = delete;
	InstanceManager& operator = (const InstanceManager&) = delete;

public:
	static InstanceManager& getInstance()
	{
		if (s_pInstance == nullptr)
		{
			s_pInstance = std::unique_ptr<InstanceManager>(new InstanceManager());
		}
		return *(s_pInstance.get());
	}

public:
	void add(Instance *pInstance);
	void clear();

private:
	static std::unique_ptr<InstanceManager> s_pInstance;
	std::deque<InstancePtr> m_intances;
};

template<class T>
class Singleton : public Instance
{
public:
	virtual ~Singleton() = default;

protected:
	Singleton() = default;
	Singleton(const Singleton&) = delete;
	Singleton& operator = (const Singleton&) = delete;

public:
	static T& getInstance()
	{
		if (s_pInstance == nullptr)
		{
			s_pInstance = new T;
		}
		return *s_pInstance;
	}

private:
	static T* s_pInstance;
};
template<class T>
T* Singleton<T>::s_pInstance;

#define SINGLETON(NAME) NAME::getInstance()



